﻿//使用jquery封装部分通用方法
var mybase = {};

if (window.$ && !$.easyui) {
    console.warn("请在Funstep.js文件前，引用easyui插件");
}

//#region 通用提示
/**
* 弹出警告
* @param {string} msg 警告语
* @param {function} callback 回调
*/
mybase.alert = function (msg, callback) {
    $.messager.alert('提示', msg, undefined, callback);
   // callback && callback();
};

/**
 * 提示语
 * @param {string} msg 提示语
 */
mybase.info = function (msg) {
    $.messager.show({
        title: '提示',
        msg: msg,
        timeout: 4000,
        showType: 'slide',
        height: 120,
        closable: true
    });
};

/**
 * 异常提示
 * @param {string} msg 异常提示语
 * @param {function} fn 关闭后触发的回调
 */
mybase.error = function (msg, fn) {
    if (window.$ && $.messager) {
        $.messager.alert('出现异常', msg, 'error', fn);
    } else {
        alert(msg);
        fn && fn();
    }
};

/**
 * 提示用户输入框
 * @param {string} msg 提示语
 * @param {function} fn 回调
 * @param {string} title 标题
 * @param {string} defaultMsg 默认值
 * @param {string} fn2 未填值的回调
 */
mybase.prompt = function (msg, fn, title, defaultMsg,fn2) {
    msg = msg || '';
    fn = fn || $.noop;
    title = title || '请输入值';
    defaultMsg = defaultMsg || '';

    var $msg = $.messager.prompt(title, msg, function (r) {
        if (r !== undefined) {
            fn(r);
        }
        else {
            fn2 && fn2(r);
        }
    });
    if (defaultMsg) {
        $msg.find('.messager-input').val(defaultMsg);
    }
    $msg.closest('.messager-window').find('.window-header .panel-tool').hide();
};

mybase.confirm = function (msg, fn, fn2) {
    var $msg = $.messager.confirm('提示', msg, function (r) {
        if (r) {
            fn && fn();
        }
        else {
            fn2 && fn2();
        }
    });
    $msg.closest('.messager-window').find('.window-header .panel-tool').hide();
};
//#endregion 

/**
 * 获取url参数
 * @param {string} name 键值
 * @param {string} href 默认为location.href
 * @returns {string} 键值
 */
mybase.getQueryString = function (name, href) {
    href = href || window.location.search;
    var reg = new RegExp("(\\?|^|&)" + name + "=([^&]*)(&|$)", 'i');
    var r = href.match(reg);
    if (r !== null)
        return decodeURIComponent(r[2]);
    return "";
};

/**
 * 获取绝对的url
 * @param {string} url 相对的url
 * @returns {string} 绝对的url
 */
mybase.getAbsolutelyUrl = function (url) {
    var a = $("<a/>", { href: url });
    var newUrl = a.prop("href");
    return newUrl;
};

/**
 * 生成唯一的ID，通过当前时间戳+随机数
 * @returns {string} 唯一值
 * */
mybase.getUniqueID = function () {
    return new Date().getTime() + "" + Math.floor(Math.random() * 1000000);
};

/**
 * 安全的脏检查
 * @param {object} scope angularjs的scope
 */
mybase.angularjsApply = function (scope) {
    if (!scope) {
        return;
    }
    if (!scope.$root.$$phase) {
        scope.$apply();
    }
};

//#region 日期相关方法
/**
 * 日期转换为相对时间 刚刚，3分钟前，4小时前，3天前
 * @param {any} date 日期字符串或者日期对象
 * @returns {string} 相对事件描述
 */
mybase.TimeformatMsg = function (date) {
    var minute = 1000 * 60;
    var hour = minute * 60;
    var day = hour * 24;
    var halfamonth = day * 15;
    var month = day * 30;
    var year = month * 12;
    var now = new Date().getTime();
    var diffValue = now - (new Date(date)).getTime();
    if (diffValue < 0) { return; }
    var yearC = diffValue / year;
    var monthC = diffValue / month;
    var weekC = diffValue / (7 * day);
    var dayC = diffValue / day;
    var hourC = diffValue / hour;
    var minC = diffValue / minute;
    if (yearC >= 1) {
        result = "" + parseInt(yearC) + "年前";
    }
    else if (monthC >= 1) {
        result = "" + parseInt(monthC) + "月前";
    }
    else if (weekC >= 1) {
        result = "" + parseInt(weekC) + "周前";
    }
    else if (dayC >= 1) {
        result = "" + parseInt(dayC) + "天前";
    }
    else if (hourC >= 1) {
        result = "" + parseInt(hourC) + "小时前";
    }
    else if (minC >= 1) {
        result = "" + parseInt(minC) + "分钟前";
    } else
        result = "刚刚";
    return result;
};

/**
 * 日期格式化 
 * 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符，
 * 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
 * 例子：
 * dateFormat("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
 * dateFormat("yyyy-M-d h:m:s.S")      ==> 2006-7-2 8:9:4.18
 * @param {any} date 日期字符串或者日期对象
 * @param {any} fmt 转换格式，如 yyyy-MM-dd hh:mm:ss.S
 * @returns {string} 日期字符串
 */
mybase.dateFormat = function (date, fmt) {
    date = date || '';
    var dateObj = date;
    if (typeof date === 'string') {
        var dateStr = date.replace('/-/g', '/');
        dateObj = new Date(dateStr);
    }

    var o = {
        "M+": dateObj.getMonth() + 1, //月份 
        "d+": dateObj.getDate(), //日 
        "h+": dateObj.getHours(), //小时 
        "m+": dateObj.getMinutes(), //分 
        "s+": dateObj.getSeconds(), //秒 
        "q+": Math.floor((dateObj.getMonth() + 3) / 3), //季度 
        "S": dateObj.getMilliseconds() //毫秒 
    };
    if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (dateObj.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
        if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
};
//#endregion 

//#region 单例提交事件
//options :事件回调 或者 参数 
window.$ && ($.fn.fsSingtonClick = function (fsOptions) {

    $(this).each(function () {
        init.apply(this, [fsOptions]);
    });

    function init(options) {
        var defaultOpt = {
            event: $.noop,
            eventHandler: 'click',
            loadingText: '提交中', //提示文字
            autoSetLoadingText: false,//是否自动设置提示文字
            group: '', //分组，如果一个组中的一个元素正在提交,其余的按钮也会处于禁用状态

            maxWait: 20, //最长等待时间 (秒)
            minWait: 1 //最小等待时间 (秒)
        };

        var opt = {};
        if ($.isFunction(options)) {
            opt = $.extend(true, {}, defaultOpt);
            opt.event = options;
        }
        else {
            opt = $.extend(true, {}, defaultOpt, options);
        }

        //#region 样式注入
        if ($("style[fs-sington-click-style]").length <= 0) {
            var styleHtml = '\
<style fs-sington-click-style>\
    .fs-sington-click-in-progress{\
        cursor: not-allowed !important;\
        filter: alpha(opacity=65);\
        -webkit-box-shadow: none;\
        box-shadow: none;\
        opacity: .65;\
    }\
    .fs-sington-click-in-progress:hover{\
        text-decoration: none; \
    } \
</style>';
            $("head").append(styleHtml);
        }
        //#endregion             

        var $element = $(this);
        var loadingText = opt.loadingText;
        var origionText = $element.html();
        $element.addClass('fs-sington-click');
        if (opt.group) {
            $element.attr('fs-sington-click-group', opt.group);
        }


        var minWaitTimeHandle = -1;
        var maxWaitTimeHandle = -1;

        $element.on(opt.eventHandler, function () {
            if ($element.hasClass("fs-sington-click-in-progress")) {
                return false;
            }
            if ($element.is("[disabled]")) {
                return false;
            }

            if ($.isFunction(opt.event)) {
                var promiseObj = opt.event.apply($element);

                if (promiseObj && $.isFunction(promiseObj.always)) {
                    $element.addClass('fs-sington-click-processing');
                    setProcessStart();

                    maxWaitTimeHandle = setTimeout(function () {
                        $element.removeClass('fs-sington-click-processing');
                        setProcessFinish();
                    }, opt.maxWait * 1000);

                    promiseObj.always(function () {
                        $element.removeClass('fs-sington-click-processing');
                        setProcessFinish();
                    });
                }
                else if (opt.minWait > 0) {
                    setProcessStart();
                }
            }
            return false;
        });


        function setProcessStart() {
            opt.autoSetLoadingText && $element.text(loadingText);
            $element.addClass("fs-sington-click-in-progress");
            if (opt.group) {
                $('.fs-sington-click[fs-sington-click-group="' + opt.group + '"]').addClass("fs-sington-click-in-progress");
            }

            if (opt.minWait > 0) {
                minWaitTimeHandle = setTimeout(function () {
                    minWaitTimeHandle = -1;
                    if (!$element.hasClass('fs-sington-click-processing')) {
                        setProcessFinish();
                    }
                }, opt.minWait * 1000);
            }
        }

        function setProcessFinish() {
            if (maxWaitTimeHandle > 0) {
                clearTimeout(maxWaitTimeHandle);
                maxWaitTimeHandle = -1;
            }

            if (minWaitTimeHandle > 0) {
                return;
            }

            $element.removeClass("fs-sington-click-in-progress");
            $element.html(origionText);
            if (opt.group) {
                $('.fs-sington-click[fs-sington-click-group="' + opt.group + '"]').removeClass("fs-sington-click-in-progress");
            }
        }
    }
});
//#endregion//#region 后台请求方法mybase.post = function (url, postData, callback, customError) {    var defer = $.Deferred();    $.ajax({        url: url,        dataType: 'json',        method:'post',        data: JSON.stringify(postData),        contentType: 'application/json',        success: function (json) {            if (json.success === false && customError !== true) {
                if (json.failure === 2) {//未登录，跳转到登录页面
                    mybase.error('登录信息已过期,请重新登录', function () {
                        location.reload();
                    });
                    console.error('登录信息已过期');
                    
                    return;
                }

                if (json.failure !== 3) {
                    error(json.msg);
                } else {
                    console.error('远程请求异常:' + json.msg);
                }
                defer.reject(json);
                return;
            }

            if (json.statusCode !== undefined && json.statusCode !== 0 && customError !== true) {
                error(json.statusMsg || '调用远程接口失败');
                deferred.reject && deferred.reject(json);
                return;
            }

            if (json.data && json.data.content) {
                try {
                    var content = JSON.parse(json.data.content);
                    if (content.statusCode !== undefined && content.statusCode != 0) {
                        error(content.statusMsg || '请求异常');
                        deferred.reject && deferred.reject(content);
                    }
                    //return;
                }
                catch (e) {
                    ;
                }
            }

            if (!json.rows) {
                json.rows = [];
            }            defer.resolve(json);        }
    });    return defer.promise();    function error(msg) {        if (mybase.error) {            mybase.error(msg);        }        else {            alert(msg);        }    }};//#endregion //#region 浏览器判断mybase.IEVersion = function () {
    var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串  
    var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器  
    var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器  
    var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
    if (isIE) {
        var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
        reIE.test(userAgent);
        var fIEVersion = parseFloat(RegExp["$1"]);
        if (fIEVersion == 7) {
            return 7;
        } else if (fIEVersion == 8) {
            return 8;
        } else if (fIEVersion == 9) {
            return 9;
        } else if (fIEVersion == 10) {
            return 10;
        } else {
            return 6;//IE版本<=7
        }
    } else if (isEdge) {
        return 'edge';//edge
    } else if (isIE11) {
        return 11; //IE11  
    } else {
        return -1;//不是ie浏览器
    }
};mybase.browserType = function () {
    var userAgent = navigator.userAgent;
    //微信内置浏览器
    if (userAgent.match(/MicroMessenger/i) == 'MicroMessenger') {
        return "MicroMessenger";
    }
    //QQ内置浏览器
    else if (userAgent.match(/QQ/i) == 'QQ') {
        return "QQ";
    }
    //Chrome
    else if (userAgent.match(/Chrome/i) == 'Chrome') {
        return "Chrome";
    }
    //Opera
    else if (userAgent.match(/Opera/i) == 'Opera') {
        return "Opera";
    }
    //Firefox
    else if (userAgent.match(/Firefox/i) == 'Firefox') {
        return "Firefox";
    }
    //Safari
    else if (userAgent.match(/Safari/i) == 'Safari') {
        return "Safari";
    }
    //IE
    else if (!!window.ActiveXObject || "ActiveXObject" in window) {
        return "IE";
    }
    else {
        return "未定义:" + userAgent;
    }
};//#endregion mybase.safeText = function (text) {    return $('<div/>').text(text).html();};mybase.getText = function (html) {
    return $('<div/>').html(html).text();}; //#region 封装popup的方法 windowOpen windowClose windowGetInput//打开新窗口 popup window //传入options 或者 url，data，cbmybase.windowOpen = function (options) {    var defaultOpts = {        onClose: $.noop,        data:'',     //传值        padding: 20,        url: '',        winWitdh: -1,  //窗口宽度 默认使用最大        winHeight: -1, //窗口高度 默认使用最大        winId: undefined,     //窗口的唯一值，默认值和url一致        top: -1,       //窗口相对于显示器对应        left: -1       //窗口相对于显示器对应    };    var opt = {};    if ($.isPlainObject(options)) {
        opt = $.extend(true, {}, defaultOpts, options);    }    else {
        opt = $.extend(true, {}, defaultOpts);        opt.url = arguments[0];        opt.data = arguments[1];        opt.onClose = arguments[2];    }
    //#region 值处理
    if (opt.winId === undefined) {
        opt.winId = opt.url;
    }
    if (opt.winWitdh <= 0) {
        opt.winWitdh = screen.width - opt.padding * 2;
    }

    var extHeight = 30; //地址栏
    if (mybase.browserType() == 'Chrome') {
        extHeight = 50;//因为chrome无法隐藏地址栏，需要额外减去高度
    }

    if (opt.winHeight <= 0) {
        opt.winHeight = screen.availHeight - opt.padding * 2 - extHeight;
    }
    if (opt.left <= 0) {
        opt.left = (screen.width - opt.winWitdh) / 2;
    }
    if (opt.top <= 0) {
        opt.top = (screen.availHeight - opt.winHeight - extHeight) / 2;
    }
    //#endregion 

    var winOpts = 'height=' + opt.winHeight + ',width = ' + opt.winWitdh + ',top=' + opt.top + ',left=' + opt.left;
    winOpts += ',toolbar=no,menubar=no,scrollbars=yes,resizable=no,location=0,status=0';

    var sessionId = mybase.getUniqueID();
    var curWindHandler = window.open(opt.url + '?sessionId=' + sessionId, opt.winId + mybase.getUniqueID(), winOpts);
    curWindHandler.funstepWinId = opt.winId;
    
    //curWindHandler.funstepInputData = JSON.stringify(opt.data);
    mybase.windowSetSessionValue(sessionId, opt.data);

    curWindHandler.funstepWinClose = function (data) {
        opt.onClose && opt.onClose(data);
        setTimeout(function () {
            try {
                curWindHandler = null;
                mybase.windowRemoveSessionValue(sessionId);
            } catch (e) {
                ;
            }
        }, 2000);
    };};mybase.windowSetSessionValue = function (id, data) {    if (!window.localStorage) {        alert('您的浏览器太过陈旧，请使用现代浏览器.');        return;    }    var jsonStr = JSON.stringify(data);    localStorage.setItem('popupSessionData-' + id, jsonStr);};mybase.windowGetSessionValue = function (id) {    var jsonStr = localStorage.getItem('popupSessionData-' + id);    if (!jsonStr) {        return undefined;    }    else {        return JSON.parse(jsonStr);    }};mybase.windowRemoveSessionValue = function (id) {    localStorage.removeItem('popupSessionData-' + id);};mybase.windowRemoveAllSession = function () {    var keyArr = [];    for (var key in localStorage) {        key = key || "";        if (key.indexOf('popupSessionData') >= 0) {            keyArr.push(key);        }    }    for (var i = 0; i < keyArr.length; i++) {        localStorage.removeItem(keyArr[i]);    }};//popup window 关闭mybase.windowClose = function (data) {    if (!window.funstepWinId) {        console.warn('不是由funstep.windowOpen 方法打开');    }    else {        try {            if (data === undefined) {                data = true;            }            funstepWinClose(data);        }        catch (e) { ;}    }    window.close();};//popup 获取传入的值mybase.windowGetInput = function () {    //if (window.funstepInputData) {    //    return JSON.parse(window.funstepInputData);    //}    //else {    //    return undefined;    //}    var sessionId = mybase.getQueryString('sessionId');    return mybase.windowGetSessionValue(sessionId);};
//当前窗口是不是 popup 窗口
function isPopupWindow() {
    var ret = false;
    if (window.opener != null) {
        if (window.name != window.opener.name) {
            ret = true;
        }
    }
    return ret;
}//#endregion 
//将easyui的datagrid 再一次封装，用于方便 删除 修改等操作
window.$ && ($.fn.mydatagrid = function (opt) {
    //删除按钮 delDom
    //修改按钮 editDom
    //删除事件 delEvent
    //修改事件 editEvent

    var $this = $(this);

    //#region 编辑和删除事件
    function checkChange() {
        var rows = $this.datagrid('getChecked');
        if (opt.editDom) {
            if (rows.length !== 1) {
                $(opt.editDom).attr("fs-old-title", $(opt.editDom).attr('title'));
                $(opt.editDom).addClass("fs-disabled").attr('title', '请选中一行进行操作');
            }
            else {
                $(opt.editDom).attr("title", $(opt.editDom).attr('fs-old-title'));
                $(opt.editDom).removeClass("fs-disabled");
            }
        }
        if (opt.delDom) {
            if (rows.length <= 0) {
                $(opt.delDom).attr("fs-old-title", $(opt.delDom).attr('title')||'删除');
                $(opt.delDom).addClass("fs-disabled").attr('title', '至少选中一行进行删除');
            }
            else {
                $(opt.delDom).attr("title", $(opt.delDom).attr('fs-old-title'));
                $(opt.delDom).removeClass("fs-disabled");
            }
        }
    }
    if (opt.delDom || opt.editDom) {
        var old_onCheck = opt.onCheck;
        var old_onUncheck = opt.onUncheck;

        checkChange();

        opt.onCheck = function (rowIndex, rowData) {
            checkChange(rowIndex, rowData);
            old_onCheck && old_onCheck(rowIndex, rowData);
        };
        opt.onUncheck = function (rowIndex, rowData) {
            checkChange(rowIndex, rowData);
            old_onUncheck && old_onUncheck(rowIndex, rowData);
        };

        opt.onCheckAll = checkChange;
        opt.onUncheckAll = checkChange;

        if (opt.delDom && opt.delEvent) {
            $(opt.delDom).click(function () {
                if ($(this).hasClass('fs-disabled')) {
                    return false;
                }

                mybase.confirm('确定进行删除吗?', function () {
                    var rows = $this.datagrid('getChecked');

                    var defer = opt.delEvent(rows);
                    defer.done && defer.done(function () {
                        mybase.info('删除成功');
                        $this.datagrid('reload');


                        $(opt.delDom).attr("fs-old-title", $(opt.delDom).attr('title') || '删除');
                        $(opt.delDom).addClass("fs-disabled").attr('title', '至少选中一行进行删除');
                    });
                });
                return false;
            });
        }

        if (opt.editDom && opt.editEvent) {
            $(opt.editDom).click(function () {
                if ($(this).hasClass('fs-disabled')) {
                    return false;
                }
                var rows = $this.datagrid('getChecked');
                opt.editEvent(rows[0]);

                return false;
            });
        }
    }
    //#endregion 

    var $handler = {};//$this.datagrid(opt);

    //#region 自适应加上 自动调整宽度的属性
    (function () {
        if (opt.fitColumns !== undefined) {
            return;
        }

        var tempTotalWidth = 0;
        var tempColArr = [];

        var fullOpts = $this.datagrid('options');

        if (opt.frozenColumns) {
            tempColArr = tempColArr.concat(opt.frozenColumns[0]);
        }
        else if (fullOpts.frozenColumns && fullOpts.frozenColumns.length == 1) {
            tempColArr = tempColArr.concat(fullOpts.frozenColumns[0]);
        }

        if (opt.columns) {
            tempColArr = tempColArr.concat(opt.columns[0]);
        }
        else if (fullOpts.columns && fullOpts.columns.length == 1) {
            tempColArr = tempColArr.concat(fullOpts.columns[0]);
        }

        $.each(tempColArr, function (index, item) {
            if (item.checkbox) {
                tempTotalWidth += 27;
            }
            else if (!item.width) {
                tempTotalWidth += 45;
            }
            else {
                tempTotalWidth += item.width;
            }
        });

        if ($this.closest('.datagrid-view').width() - 100 > tempTotalWidth) {
            opt.fitColumns = true;
        }
        return;
    })();
    //#endregion 

    //#region 自适应加上 自动调整行数的接口
    (function () {
        if (opt.pageSize !== undefined) {
            return;
        }
        if ($this.attr('pageSize')) {
            return;
        }

        var viewHeight = $this.closest('.datagrid-view').height();

        if (viewHeight <= 0) {
            return;
        }

        var rowHeight = 32;

        var pageSizeArr = [5, 10, 15, 20, 25, 30, 50];

        var rowSizeIndex = 0;
        while (rowSizeIndex < pageSizeArr.length) {
            if ((pageSizeArr[rowSizeIndex] + 1) * rowHeight + 50 < viewHeight) {
                rowSizeIndex++;
            }
            else {
                break;
            }
        }
        rowSizeIndex = Math.min(pageSizeArr.length - 1, rowSizeIndex);
        opt.pageSize = pageSizeArr[rowSizeIndex];
    })();
    //#endregion 

    $handler = $this.datagrid(opt);

    return $handler;
});

//将文件服务器的预览地址 由相对地址改成绝对地址
mybase.fixFastDfsUrl = function (url) {
    if (!window.FunstepConfig) {
        console.error('请先加载FunstepConfig');
        return;
    }
    if (!FunstepConfig.FastDfsViewUrl) {
        console.error('请先设置文件服务器预览地址FastDfsViewUrl');
        return;
    }
    return FunstepConfig.FastDfsViewUrl + '/' + url;
};

//#region $.fn.fsConvexHull 计算凸包
(function () {
    if (!window.$) {
        return;
    }
    if ($("head").find(".fs-convexhull-style").length <= 0) {
        var headHtml = '\
            <style class="fs-convexhull-style">\
            .fs-convexhull-container {\
                position:relative;\
                display:inline-block;\
            }\
            .fs-convexhull-canvas {\
                position: absolute;\
                top: 0;\
                left: 0;\
                width: 100%;\
                height: 100%;\
            }</style>';
        $("head").append(headHtml);
    }

})();
window.$ && ($.fn.fsConvexHull = function (options) {
    var defaultOpts = {
        paths: [], //路径点 [{x,y},{x,y}]
        imgRealWidth: 320,
        imgRadlHeight: 240
    };

    var opt = $.extend(true, {}, defaultOpts, options);

    var $this = $(this);
    var imgH = $this.height();

    $this.wrap("<div class='fs-convexhull-container'></div>");
    $this.addClass('fs-convexhull-img');
    var $container = $(this).parent();
    $container.height(imgH);

    var $canvas = $("<canvas class='fs-convexhull-canvas'></canvas>");
    var myCanvas = $canvas[0];
    $canvas.appendTo($container);
    
    var ctx = myCanvas.getContext("2d");
    myCanvas.convexHullPoints = JSON.parse(JSON.stringify(opt.paths));
    myCanvas.convexHullPaths = JSON.parse(JSON.stringify(opt.paths));

    if (!$this.width() || !$this.height()) {
        $this.on('load', function () {
            initPath();
        });
    }
    else {
        initPath();
    }

    function initPath() {
        $canvas.attr({
            width: $this.width(),
            height: $this.height()
        });
        drawCurConvexhullArea(opt.paths);
    }

    //#region canvas事件
    //右键点击移除最近新增的点
    $canvas.contextmenu(function () {
        if (!$(this).hasClass('editing')) {
            return false;
        }
        myCanvas.convexHullPoints.pop();
        myCanvas.convexHullPaths = convexHull(myCanvas.convexHullPoints);
        clearCanvas();
        drawPoint(myCanvas.convexHullPoints);
        drawPath(myCanvas.convexHullPaths);
        return false;
    });

    $canvas.click(function (e) {
        if (!$(this).hasClass('editing')) {
            return;
        }

        var x = e.clientX - $canvas.offset().left;
        var y = e.clientY - $canvas.offset().top;

        myCanvas.convexHullPoints.push({
            x: x,
            y: y
        });

        myCanvas.convexHullPaths = convexHull(myCanvas.convexHullPoints);

        clearCanvas();
        drawPoint(myCanvas.convexHullPoints);
        drawPath(myCanvas.convexHullPaths);
    });
    //#endregion 

    $this.showConvexHull = function () {
        $canvas.show();
    };

    $this.hideConvexHull = function () {
        $canvas.hide();
    };
    return $this;

    function clearCanvas() {
        ctx.clearRect(0, 0, myCanvas.width, myCanvas.height);
    }

    function drawPoint(points) {
        $.each(points, function (index, item) {
            ctx.beginPath();
            ctx.arc(item.x, item.y, 4, 0, 2 * Math.PI);
            ctx.fillStyle = "red";
            ctx.fill();
            ctx.strokeStyle = "red";
            ctx.closePath();
            ctx.stroke();
        });
    }

    function drawPath(points) {
        if (points.length < 3) {
            return;
        }

        ctx.beginPath();
        ctx.strokeStyle = "black";
        ctx.moveTo(points[0].x, points[0].y);

        for (var i = 1; i < points.length; i++) {
            ctx.lineTo(points[i].x, points[i].y);
        }
        ctx.lineTo(points[0].x, points[0].y);
        ctx.closePath();
        ctx.stroke();
    }

    //#region drawCurConvexhullArea 将当前的凸包面积画出来
    function drawCurConvexhullArea(paths) {
        clearCanvas();

        if (!paths || paths.length < 3) {
            return;
        }

        var points = fitCanvasPointFromRemotePoint(paths);

        ctx.beginPath();
        ctx.moveTo(points[0].x, points[0].y);

        for (var i = 1; i < points.length; i++) {
            ctx.lineTo(points[i].x, points[i].y);
        }
        ctx.closePath();
        ctx.globalAlpha = 0.5;
        ctx.fillStyle = "red";
        ctx.fill();
        ctx.stroke();
        ctx.globalAlpha = 1;
    }
    //#endregion 
    
    function startEdit() {
        $canvas.addClass("editing");
    }

    //清空
    function clear() {
        myCanvas.convexHullPoints = [];
        myCanvas.convexHullPaths = [];
        clearCanvas();
    }

    function fitCanvasPointToRemotePoint(paths) {
        var curHeight = $canvas.height();
        var points = $.map(paths, function (item) {
            return {
                X: parseInt(item.x / curHeight * opt.imgRadlHeight),
                Y: parseInt(item.y / curHeight * opt.imgRadlHeight)
            };
        });
        return points;
    }

    function fitCanvasPointFromRemotePoint(paths) {
        var curHeight = $canvas.height();
        var points = $.map(paths, function (item) {
            return {
                x: (item.X || item.x) * curHeight / opt.imgRadlHeight,
                y: (item.Y || item.y) * curHeight / opt.imgRadlHeight
            };
        });
        return points;
    }

    //#region convexHull 计算凸包算法 [{x:1,y:2},{x:33,y:44}]
    function convexHull(arr) {
        points = JSON.parse(JSON.stringify(arr));
        points.sort(function (a, b) {
            return a.x != b.x ? a.x - b.x : a.y - b.y;
        });

        var n = points.length;
        var hull = [];

        for (var i = 0; i < 2 * n; i++) {
            var j = i < n ? i : 2 * n - 1 - i;
            while (hull.length >= 2 && removeMiddle(hull[hull.length - 2], hull[hull.length - 1], points[j]))
                hull.pop();
            hull.push(points[j]);
        }

        hull.pop();

        function removeMiddle(a, b, c) {
            var cross = (a.x - b.x) * (c.y - b.y) - (a.y - b.y) * (c.x - b.x);
            var dot = (a.x - b.x) * (c.x - b.x) + (a.y - b.y) * (c.y - b.y);
            return cross < 0 || cross == 0 && dot <= 0;
        }

        return hull;
    }    //#endregion });
//#endregion 

//#region getFormdata 获取表单内容 对象格式 自动加点.
mybase.getFormdata = function (jqSelector) {
    var $form = $(jqSelector);

    var $item = $form.find('[name]:not([disabled])');
    var data = {};
    $item.each(function () {
        var $this = $(this);
        var thisVal = $this.val();
        var name = $this.attr('name');
        var arr = name.split('.');
        var curObj = data;

        if ($this.is('[type="checkbox"],[type="radio"]')) {
            thisVal = $form.find('[name="' + name + '"]:checked').val();
        }

        $.each(arr, function (index, item) {
            if (index == arr.length - 1) {
                curObj[item] = thisVal;
                return;
            }
            else {
                if (!curObj[item]) {
                    curObj[item] = {};
                }
                curObj = curObj[item];
            }
        });
        
    });

    return data;
};
//#endregion 

//#region setFormdata 获取表单内容 对象格式 自动加点.
mybase.setFormdata = function (data) {
    var retObj = {};

    setData("", data, retObj);

    function setData(pre, curData, totalData) {
        for (var key in curData) {
            var item = curData[key];
            var objKey = (pre && pre + ".") + key;
            if (!$.isPlainObject(item)) {
                totalData[objKey] = item;
                continue;
            }
            else {
                setData(objKey, item, totalData);
            }
        }
    }

    return retObj;
};
//#endregion 


//带进度条的表单提交功能
mybase.formSubmitProgressbar = function (options) {
    var defaultOption = {
        url: '',
        formData: new FormData(),//FormData 对象
        success: $.noop,
        dataType: 'json',
        uploadProgress: $.noop //(百分比，已上传数据，全部数据)
    };
    var opts = $.extend({}, defaultOption, options);

    var xhr = new XMLHttpRequest();
    xhr.open('post', opts.url);

    xhr.setRequestHeader("Accept", "application/json, text/javascript, */*; q=0.01");
    xhr.onreadystatechange = function () {
        opts.uploadProgress(1);
        if (xhr.readyState == 4 && xhr.status == 200) {
            if (opts.dataType == 'json') {
                opts.success(JSON.parse(xhr.responseText));
            }
            else {
                opts.success(xhr.responseText);
            }
        }
    };
    //侦查当前附件上传情况  
    xhr.upload.onprogress = function (evt) {
        var loaded = evt.loaded;//已上传
        var total = evt.total;//附件总大小  
        var per = loaded / total;  //已经上传的百分比  
        opts.uploadProgress(per, loaded, total);
    };
    xhr.send(opts.formData);
};

//上传图片 预览 
mybase.uploadImageView = function (options) {
    var defaultOption = {
        handler: '',//用于触发上传事件的按钮
        targetImage: '', //单幅图片上传时，图片目标
        imageType: 'image/bmp,image/png,image/gif,image/jpeg',
        imageCompress: false,
        imageCompressWidth: '',
        imageCompressHeight: '',
        imageCompressQuality: 1,  //压缩质量

        onComplete: $.noop  //预览完成事件
       // autoRebuild: false //选中图片后，是否自动删除文件 自动创建
    };
    var opts = $.extend({}, defaultOption, options);

    if ($(opts.handler).length <= 0) {
        console.error('请设置handler');
        return;
    }

    var $fileController = $("<input/>", {
        type: 'file',
        style: 'display:none'
    });
    $(opts.handler).after($fileController);

    //if (opts.fileController === '') {
    //    var tempFile = $("<input/>", {
    //        type: 'file',
    //        style: 'display:none'
    //    });
    //    $(opts.handler).after(tempFile);
    //    //$("body").append(tempFile);
    //    opts.fileController = tempFile;
    //}

    $fileController.attr("accept", opts.imageType);

    $(opts.handler).click(function () {
        $fileController.click();
    });

    $fileController.change(function (e) {
        var files = e.target.files;
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            imageRead(file, function (imageUrl) {
                opts.onComplete(imageUrl);
            });
        }
        $fileController.attr('fs-file-val', $fileController.val());
        $fileController.val('');
    });

    function imageRead(file, callBack) {
        var imageType = /image.*/;
        //通过type属性进行图片格式过滤  
        if (!file.type.match(imageType)) {
            if (window.bootbox) {
                dysoft.info('只能上传图片');
            }
            else {
                alert('只能上传图片');
            }
            return;
        }
        //读入文件  
        var reader = new FileReader();
        reader.onload = function (e) {
            var base64Url = e.target.result; //原图片的base64
            if (opts.imageCompress == true) {
                base64Url = imageCompress(base64Url, opts.imageCompressWidth, opts.imageCompressHeight, file.type, opts.imageCompressQuality); //压缩之后的base64
            }
            callBack(base64Url);
        };
        reader.readAsDataURL(file);
    }

    //压缩图片
    function imageCompress(originBase64Url, width, height, mime_type, quality) {
        mime_type = mime_type || "image/jpeg";
        //height = height || 50;

        var source_img_obj = new Image();
        source_img_obj.src = originBase64Url;

        var originW = source_img_obj.naturalWidth;
        var originH = source_img_obj.naturalHeight;

        var newW, newH;
        if (height && width) {
            newW = width;
            newH = height;
        }
        else if (height && !width) {
            newH = height;
            newW = Math.round(originW * newH / originH);
        }
        else if (!height && width) {
            newW = width;
            newH = Math.round(originH * newW / originW);
        }
        else {
            newW = originW;
            newH = originH;
        }
        quality = quality || 1;

        var cvs = document.createElement('canvas');
        //naturalWidth真实图片的宽度
        cvs.width = newW;
        cvs.height = newH;
        var ctx = cvs.getContext("2d").drawImage(source_img_obj, 0, 0, originW, originH, 0, 0, newW, newH);
        var newImageData = cvs.toDataURL(mime_type, quality);
        cvs.remove();
        return newImageData;
    }

    return this;
};


mybase.formPost = function (URL, PARAMS, method) {
    //if ($("#funstep_download_iframe").length <= 0) {
    //    $('<iframe/>',
    //        {
    //            id: 'funstep_download_iframe',
    //            name: 'funstep_download_iframe',
    //            style: 'display:none'
    //        }).appendTo("body");
    //}
    
    method = method || 'post';
    var temp = document.createElement("form");
    temp.action = URL;
    temp.method = method;
    temp.style.display = "none";
    //temp.target = "funstep_download_iframe";
    temp.target = "_blank";

    PARAMS = PARAMS || {};

    //temp.
    for (var x in PARAMS) {
        var opt = document.createElement("textarea");
        opt.name = x;
        opt.value = PARAMS[x];
        temp.appendChild(opt);
    }
    document.body.appendChild(temp);
    temp.submit();
    //setTimeout(function () { temp.remove(); }, 5000);
    return temp;
};

mybase.getProxyUrl = function (url) {
    url = url || '';
    if (url.substr(0, 4).toLocaleLowerCase() !== 'http') {
        return url;
    }
    return "/ApiUtils/ProxyGetAny?proxyUrl=" + encodeURIComponent(url);
};

// 格式化xml
mybase.formatXml = function (text) {
    //var formatted = '';
    //var reg = /(>)(<)(\/*)/g;
    //xml = xml.replace(reg, '$1\r\n$2$3');
    //var pad = 0;
    //jQuery.each(xml.split('\r\n'), function (index, node) {
    //    var indent = 0;
    //    if (node.match(/.+<\/\w[^>]*>$/)) {
    //        indent = 0;
    //    } else if (node.match(/^<\/\w/)) {
    //        if (pad != 0) {
    //            pad -= 1;
    //        }
    //    } else if (node.match(/^<\w[^>]*[^\/]>.*$/)) {
    //        indent = 1;
    //    } else {
    //        indent = 0;
    //    }

    //    var padding = '';
    //    for (var i = 0; i < pad; i++) {
    //        padding += '  ';
    //    }

    //    formatted += padding + node + '\r\n';
    //    pad += indent;
    //});

    //return formatted;




    // 格式化代码函数,已经用原生方式写好了不需要改动,直接引用就好
    var removeLineEnd = function (str) {
        return str.replace(/(<.+?\s+?)(?:\n\s*?(.+?=".*?"))/g, '$1 $2');
    };

    function getPrefix(prefixIndex) {
        var span = '    ';
        var output = [];
        for (var i = 0; i < prefixIndex; ++i) {
            output.push(span);
        }

        return output.join('');
    }

    //去掉多余的空格
    text = '\n' + text.replace(/(<\w+)(\s.*?>)/g, function ($0, name, props) {
        return name + ' ' + props.replace(/\s+(\w+=)/g, " $1");
    });
    text = text.replace(/>\s*?</g, ">\n<");

    //把注释编码
    text = text.replace(/\n/g, '\r').replace(/<!--(.+?)-->/g, function ($0, text) {
        var ret = '<!--' + escape(text) + '-->';
        //alert(ret);
        return ret;
    }).replace(/\r/g, '\n');

    //调整格式
    var rgx = /\n(<(([^\?]).+?)(?:\s|\s*?>|\s*?(\/)>)(?:.*?(?:(?:(\/)>)|(?:<(\/)\2>)))?)/mg;
    var nodeStack = [];
    var output = text.replace(rgx, function ($0, all, name, isBegin, isCloseFull1, isCloseFull2, isFull1, isFull2) {
        var isClosed = (isCloseFull1 == '/') || (isCloseFull2 == '/') || (isFull1 == '/') || (isFull2 == '/');
        //alert([all,isClosed].join('='));
        var prefix = '';
        if (isBegin == '!') {
            prefix = getPrefix(nodeStack.length);
        }
        else {
            if (isBegin != '/') {
                prefix = getPrefix(nodeStack.length);
                if (!isClosed) {
                    nodeStack.push(name);
                }
            }
            else {
                nodeStack.pop();
                prefix = getPrefix(nodeStack.length);
            }

        }
        var ret = '\n' + prefix + all;
        return ret;
    });

    var prefixSpace = -1;
    var outputText = output.substring(1);
    //alert(outputText);

    //把注释还原并解码，调格式
    outputText = outputText.replace(/\n/g, '\r').replace(/(\s*)<!--(.+?)-->/g, function ($0, prefix, text) {
        //alert(['[',prefix,']=',prefix.length].join(''));
        if (prefix.charAt(0) == '\r')
            prefix = prefix.substring(1);
        text = unescape(text).replace(/\r/g, '\n');
        var ret = '\n' + prefix + '<!--' + text.replace(/^\s*/mg, prefix) + '-->';
        //alert(ret);
        return ret;
    });

    return outputText.replace(/\s+$/g, '').replace(/\r/g, '\r\n');
};


mybase.getBase64Image = function (img) {
    var canvas = document.createElement("canvas");
    canvas.width = img.naturalWidth;
    canvas.height = img.naturalHeight;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight);
    var dataURL = canvas.toDataURL("image/jpeg");
    return dataURL;
};

mybase.getBase64ImagePart = function (img, x, y, width, height) {
    var canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, x, y, width, height, 0, 0, width, height);
    var dataURL = canvas.toDataURL("image/jpeg");
    return dataURL;
};

mybase.getBase64ImagePartFromBase64 = function (base64, x, y, width, height) {
    var img = new Image();
    img.src = base64;

    return mybase.getBase64ImagePart(img, x, y, width, height); 
};